<!--
 * @Description: json生成表单模块，表单验证
 * @Author: Boide
 * @Date: 2021-09-06 18:00:01
 * @LastEditors: guiyi@hongyi.tech
 * @LastEditTime: 2021-09-13 23:22:50
-->
<template>
  <div>
    <el-form class="HyForm" :class="{'modal': isModal}" label-width="120px" :ref="formRef" :model="formModel" :rules="formRules">
      <el-row>
      <template v-for="(item, i) in formConf">
        <el-col :key="i" :span="12*item.cell">
          <el-form-item
            :prop="item.model"
            :rules="formRules[item.model]"
            :label='item.showName+":"'
          >
            <!-- 输入框 -->
            <el-input
              v-if="item.ftype=='text'"
              class="width80"
              :placeholder="`请输入${item.showName}`"
              v-model="formModel[item.model]"
              :disabled="item.once"
            />
            <!-- 富文本 -->
            <tinymce
              v-if="item.ftype=='richText'"
              class="width80"
              v-model="formModel[item.model]"
              :height="300"
            />
            <!-- 文本框 -->
            <el-input
              v-else-if="item.ftype=='textarea'"
              type="textarea"
              class="width80"
              :autosize="{ minRows: 4, maxRows: 4 }"
              :placeholder="`请输入${item.showName}`"
              v-model="formModel[item.model]"
              :disabled="item.once"
            />
            <!-- 数字框 -->
            <el-input-number
              v-else-if="item.ftype=='number'"
              controls-position="right"
              :min="0" :max="99999"
              v-model="formModel[item.model]"
              :disabled="item.once"
            />
            <!-- switch开关 -->
            <el-switch
              v-else-if="item.ftype=='switch'"
              :active-value="item.options.map(o=>o.id).sort()[1]"
              :inactive-value="item.options.map(o=>o.id).sort()[0]"
              v-model="formModel[item.model]"
              :disabled="item.once"
            />
            <!-- 单项选择框 -->
            <el-select
              v-else-if="item.ftype=='select'"
              v-model="formModel[item.model]"
              :placeholder="`请选择${item.showName}`"
              :size="item.size"
              :disabled="item.once"
            >
              <el-option
                v-for="v in item.options"
                :key="v.id"
                :label="v.value"
                :value="v.id"
              />
            </el-select>
            <!-- 时间选择框 -->
            <el-date-picker
              v-else-if="item.ftype=='dateTime'"
              v-model="formModel[item.model]"
              :type="item.dateFormatter.length===10?'date':'datetime'"
              :placeholder="`请选择${item.showName}`"
              :format="item.dateFormatter"
              :value-format="item.dateFormatter"
              :clearable="false"
              :disabled="item.once"
            />
            <!-- 颜色选择器 -->
            <el-color-picker
              v-else-if="item.ftype=='color'"
              v-model="formModel[item.model]"
              :disabled="item.once"
            />
            <!-- 图片上传 -->
            <upload-img
              v-else-if="item.ftype=='image'"
              v-model="formModel[item.model]"
              :action="item.url"
              :maxSize="item.size"
              :multipleMax="item.count"
              :accept="item.suffix.join(',')"
              :multiple="item.multiple"
              :disabled="item.once"
            />
            <!-- 文件上传 -->
            <el-upload
              v-else-if="item.ftype=='file'"
              :action="item.url"
              :accept="item.suffix.join(',')"
              :show-file-list="false"
              :on-success="res => handleSuccess(res, item.model)"
              :before-upload="file => beforeUpload(file, item)"
              :disabled="item.once"
            >
              <el-button size="small" type="primary">点击上传</el-button>
              <div v-if="formModel[item.model]" slot="tip" class="upload-title">
                {{!!formModel[item.model]&&formModel[item.model].split(`@=#=@`)[0]}}
              </div>
            </el-upload>
          </el-form-item>
        </el-col>
      </template>
      </el-row>
      <el-form-item v-if="!isModal" label=' '>
        <el-button :loading="loading" type="primary" @click="submitForm">提交</el-button>
        <el-button @click="cancel">取消</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
import UploadImg from '../upload-img'
import Tinymce from '../Tinymce'
function isString(str){
  return (typeof str=='string')&&str.constructor==String;
}
export default {
  name: 'hy-form',
  components: { UploadImg, Tinymce },
  props: {
    formData: {
      type: Array,
      default() {
        return []
      }
    },
    formRef: {
      type: String,
      default: 'from'+new Date().getTime()
    },
    value: {
      type: Object,
      default() {
        return {}
      }
    },
    loading: {
      type: Boolean,
      default: false
    },
    isModal: {
      type: Boolean,
      default: false
    }
  },
  data() {
    if (!this.formData.length) return { formConf: [] }
    const data = {
      formConf: JSON.parse(JSON.stringify(this.formData)),
      formModel: {},
      formRules: {},
      formActive: false
    }
    this.initFormModel(data.formConf, data.formModel)
    this.initFormRules(data.formConf, data.formRules)
    return data
  },
  watch: {
    value(newVal) {
      let obj = {}
      for (const key in newVal) {
        let val = newVal[key]
        let [{multiple=false}] = this.formConf.filter(o => o.model === key).length ?
          this.formConf.filter(o => o.model === key) : [{}]
        if (val>1000000000000&&new Date(val!='Invalid Date')) {
          obj[key] = new Date(val)
        } else if (val&&isString(val)&&multiple) {
          obj[key] = val.split('@!#!@')
        } else if (multiple) {
          obj[key] = []
        } else {
          obj[key] = val
        }
      }
      this.formModel = { ...obj }
    }
  },
  mounted() {
    this.$emit('mounted', this.$refs[this.formRef]);
  },
  methods: {
    beforeUpload(file, item) {
      let fileType = file.name.substring(file.name.lastIndexOf('.') + 1)
      const istype = item.suffix.includes(fileType)
      if (!istype) {
        this.$message.error(`上传的格式只能为；${item.suffix.join(',')}`)
      }
      return istype
    },
    handleSuccess(res, model) {
      const { fileName, path } = res.data
      this.$set(this.formModel, model, fileName+'@=#=@'+path)
    },
    // 提交表单，提交之前校验表单
    submitForm() {
      this.$refs[this.formRef].validate(async valid => {
        if (valid) {
          let formObj = {}
          for (const key in this.formModel) {
            const val = this.formModel[key]
            formObj[key] = Array.isArray(val) ? val.join('@!#!@') : val
          }
          this.$emit('input', formObj)
          this.$emit('sumbit', formObj)
        }
      })
    },
    // 取消
    cancel() {
      this.$emit('input', {})
      this.resetForm(this.formRef)
      this.$store.dispatch('tagsView/delView', this.$route)
      this.$router.go(-1)
    },
    initFormModel(componentList = [], formModel) {
      componentList.forEach(cur => {
        if (cur.model) {
          if (['select','switch'].includes(cur.ftype)) {
            if (cur.multiple) {
              formModel[cur.model] = (cur.initValue || []).map(o => parseInt(o))
            } else {
              formModel[cur.model] = cur.initValue ? parseInt(cur.initValue) : ''
            }
          } else {
            formModel[cur.model] = cur.initValue || (cur.multiple ? [] : '')
          }
        }
      })
    },
    initFormRules(componentList = [], formRules) {
      componentList.forEach(cur => {
        const { required } = cur
        if (cur.model&&required) {
          if (['dateTime','select','file', 'image'].includes(cur.ftype)) {
            formRules[cur.model] = [{required, message: `请选择${cur.showName}`}]
          } else {
            formRules[cur.model] = [{required, message: `请输入${cur.showName}`}]
          }
        }
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.width80{
  width: 80% !important;
  max-width: 928px !important;
}
.modal{
  .width80{
    width: 100% !important;
    max-width: 100% !important;
  }
}
</style>
